package indigo.mybatis.template;

import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import org.apache.ibatis.builder.BuilderException;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.session.Configuration;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.runtime.RuntimeInstance;
import org.apache.velocity.runtime.parser.ParseException;

import com.google.common.collect.Maps;

import indigo.mybatis.entity.EntityMetadata;

public class VelocityTemplateMapperBuilder implements TemplateMapperBuilder {
	private static final RuntimeInstance runtimeInstance;
	static {
		runtimeInstance = new RuntimeInstance();
		runtimeInstance.init();
	}

	private final String templateName;
	private final String templateText;

	public VelocityTemplateMapperBuilder(String templateName, String templateText) {
		this.templateName = templateName;
		this.templateText = templateText;
	}

	@Override
	public void build(Configuration configuration, EntityMetadata<?> entityMetadata) {
		Template template = new Template();
		template.setRuntimeServices(runtimeInstance);
		try {
			template.setData(runtimeInstance.parse(templateText, templateName));
		} catch (ParseException e) {
			throw new BuilderException("Failed to compile velocity template: " + templateName, e);
		}
		template.initDocument();

		Map<String, Object> contextValues = Maps.newHashMap();
		contextValues.put("metadata", entityMetadata);
		StringWriter writer = new StringWriter();
		template.merge(new VelocityContext(contextValues), writer);

		XMLMapperBuilder builder = new XMLMapperBuilder(
				new ByteArrayInputStream(writer.toString().getBytes(StandardCharsets.UTF_8)),
				configuration,
				templateName,
				configuration.getSqlFragments());
		builder.parse();
	}
}
